﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using daDataLayer;
using System.IO;
using System.Text.RegularExpressions;
using System.Reflection;
using daStaticAnalyser.Analysers;
using daStaticAnalyser;

namespace danalyser.Interface.Dialogs
{
    // Свойства и контроллеры
    using Properties;
    using Controllers;

    /// <summary>
    /// Окно настроек
    /// </summary>
    public partial class MainSettingsForm : Form
    {
        private static Regex filter = new Regex("[/\\:*?\"<>|]");

        public MainSettingsForm()
        {
            InitializeComponent();
        }

        /// <summary>
        /// Перегрузка метода отображения окна
        /// </summary>
        public new void ShowDialog()
        {
            profileBox.Items.Clear();
            profileBox.Items.Add("default");
            DirectoryInfo directory = new DirectoryInfo(string.Format("{0}\\profiles", FileController.Instance.StartupPath));
            DirectoryInfo[] subdirs = directory.GetDirectories();
            foreach (DirectoryInfo subdir in subdirs)
                if (!profileBox.Items.Contains(subdir.Name))
                    profileBox.Items.Add(subdir.Name);
            if (!profileBox.Items.Contains(AnalysisController.Instance.Profile))
                profileBox.Items.Add(AnalysisController.Instance.Profile);
            profileBox.SelectedItem = AnalysisController.Instance.Profile;
            loadIfNeedCheck.Checked = Settings.Default.LoadModulesIfNeed;
            askToSaveFormattedCheck.Checked = Settings.Default.askToSaveFormatted;
            base.ShowDialog();
        }

        /// <summary>
        /// Клик по кнопке "ОК"
        /// </summary>
        private void okBtn_Click(object sender, EventArgs e)
        {
            if ((profileBox.Text.Length == 0) || (profileBox.Text == ".") || (profileBox.Text == "..") || (filter.IsMatch(profileBox.Text)))
                MessageBox.Show("Вы использовали недопустимые символы в имени профиля (/, \\, :, *, ?, \", <, >, |),\r\nзадали запрещенное имя (. или ..), или оставили имя пустым!", "Внимание", MessageBoxButtons.OK, MessageBoxIcon.Warning);
            else
            {
                Settings.Default.LoadModulesIfNeed = loadIfNeedCheck.Checked;
                Settings.Default.askToSaveFormatted = askToSaveFormattedCheck.Checked;
                AnalysisController.Instance.SaveProfile(profileBox.Text);
                Close();
            }
        }

        /// <summary>
        /// Клик по кнопке "Отмена"
        /// </summary>
        private void cancelBtn_Click(object sender, EventArgs e)
        {
            this.Close();
        }

        private void button1_Click(object sender, EventArgs e)
        {
            if (openFile.ShowDialog() == DialogResult.OK)
            {
                AddAnalyzator();
            }
        }

        /// <summary>
        /// Динамическое подключение статического анализатора
        /// </summary>
        private void AddAnalyzator()
        {
            //Содержит ли dll классы статических анализаторов
            if (!ValidStatAnalizator(openFile.FileName))
            {
                //Если нет, то сообщаем пользователю и авыходим
                MessageBox.Show(openFile.FileName + " не содержит статических анализаторов");
                return;
            }

            //Если да, то копируем dll в папку с динамически подключаемыми стат. анализаторами
            String st = Application.StartupPath;
            FileInfo fileinfo = new FileInfo(openFile.FileName);
            string path = st + @"\..\..\..\Analizators\"
                + fileinfo.Name;
            File.Copy(openFile.FileName, path);

            //и обновляем список стат. анализаторов
            StaticAnalyserController.Instance.UpdateAnalysers();
            analyzersBox.Items.Add(openFile.FileName);
        }

        /// <summary>
        /// Проверка на содержание в dll класса статического анализатора
        /// </summary>
        /// <param name="fn">Путь к dll</param>
        /// <returns>bool - dll содержит стат.анализатор, false - не содержит</returns>
        private bool ValidStatAnalizator(String fn)
        {
            Assembly a = Assembly.LoadFrom(fn);//Загружаем сборку
            foreach (Type type in a.GetTypes())//Проходимся по всем типам сборки
            {
                if (type.IsClass)//Рассматриваем только классы
                {
                    try
                    {
                        object obj = type.InvokeMember("new", BindingFlags.CreateInstance, null, null, null);//Вот здесь создаётся экземпляр класса по type
                        if (obj is BaseStaticAnalyser)//Если это класс стат.анализатор
                        {
                            return true;
                        }
                    }
                    catch
                    {
                        continue;
                    }
                }
            }
            return false;
        }

        private void MainSettingsForm_Load(object sender, EventArgs e)
        {
            //Получение списка статических анализаторов
            string path = @"..\..\..\Analizators";//Папка в которой расположены стат. анализаторы
            DirectoryInfo directoryinfo = new DirectoryInfo(path);
            FileInfo[] fileinfo = directoryinfo.GetFiles("*.dll");//Рассматриваем только dll
            foreach (FileInfo thisfileinfo in fileinfo)//Проходимся по всем библиотекам
            {
                if (ValidStatAnalizator(thisfileinfo.FullName))
                {
                    analyzersBox.Items.Add(thisfileinfo.FullName);    
                }
            }
        }
    }
}
